/*
 * AbstractElements.cpp
 *
 *  Created on: 2010-9-26
 *      Author: wenjian
 */

#include "AbstractElements.h"
#include "AbstractElement.h"
#include "AbstractLayer.h"

using namespace std;
using namespace Thk;
namespace Ed {

  AbstractElements::AbstractElements():sortFlag(false), mouseHoveringElement(NULL){
  }
  AbstractElements::AbstractElements(AbstractElement* e):sortFlag(false), mouseHoveringElement(NULL){
    add(e);
  }
  AbstractElements::AbstractElements(const std::vector<AbstractElement*>* es):sortFlag(false), mouseHoveringElement(NULL){
    addAll(es);
  }
  AbstractElements::~AbstractElements() {

  }


  /**
   * 加入元素, 如果元素已经存在，可改变其位置
   */
  bool AbstractElements::add(AbstractElement* e, int pos){
    if(!e){
      return false;
    }
    int elsSize = elements.size();
    VElements::iterator it = getPosition(e);
    if (it != elements.end()){//存在
      pos = pos<0?0:(pos>elsSize?elsSize:pos);
      if(*it == elements[pos]){
        return true;
      }
      VElements::iterator begin = elements.begin();
      if((it-begin)<pos){
        pos--;
      }
      elements.erase(it);
      elements.insert(elements.begin()+pos, e);
    }else{//不存在
      if(pos>=elsSize){
        elements.push_back(e);
      }else{
        elements.insert(elements.begin()+pos, e);
      }
    }
    setSortFlag(false);
    return true;
  }

  /**
   * 加入除excluded以外的所有元素
   */
  void AbstractElements::addAllAndExclude(const std::vector<AbstractElement*>* els, const AbstractElement* excluded){
    if(!els->empty()){
      std::vector<AbstractElement*>::const_iterator it = els->begin();
      for(; it != els->end(); it++){
        AbstractElement* e = *it;
        if(excluded!=NULL && e == excluded){
          continue;
        }
        if(!contains(e)){
          elements.push_back(e);
          setSortFlag(false);
        }
      }
      //destroyBoundRect();
//      createBoundRect();
    }
  }

  /**
   * 移除元素
   */
  bool AbstractElements::remove(AbstractElement* e) {
    if(!e){
      return false;
    }
    VElements::iterator  it = getPosition(e);
    if (it != elements.end()) {
      remove(it);
      //destroyBoundRect();
//      createBoundRect();
      setSortFlag(false);
      return true;
    }
    return false;
  }



  /**
   * 清除所有元素
   */
  void AbstractElements::clear(){
    if(!elements.empty()){
      mouseHoveringElement = NULL;
      elements.clear();
      setSortFlag(false);
    }
    //destroyBoundRect();
//    createBoundRect();
  }


  /**
   * 移除参数<code>excluded</code>元素以外的元素, 在v中返回被移除的元素, excluded指示不被移除的元素,
   * v可以为NULL, 即不返回被移除的元素
   */
  std::vector<AbstractElement*>* AbstractElements::removesAndExclude(vector<AbstractElement*>* v, const AbstractElement* excluded){
    if(elements.empty()){
      return v;
    }
    size_t count = elements.size();
    for (VElements::iterator it = elements.begin(); it != elements.end();) {
      if(excluded==NULL || (*it) != excluded){
        if(v){
          v->push_back(*it);
        }
        remove(it);
      }else{
        it++;
      }
    }
    if(elements.size()!=count){
      setSortFlag(false);
      //destroyBoundRect();
//      createBoundRect();
    }
    return v;
  }

  /**
   * 移除参数<code>excludeds</code>元素以外的元素, 在v中返回被移除的元素, excludeds指示不被移除的元素
   * v可以为NULL, 即不返回被移除的元素, excludeds中的元素必须是已经被排序过
   */
  std::vector<AbstractElement*>* AbstractElements::removesAndExcludes(vector<AbstractElement*>* v, const std::vector<AbstractElement*>* excludeds){
    if(elements.empty()){
      return v;
    }
    size_t count = elements.size();
    for (VElements::iterator it = elements.begin(); it != elements.end();) {
      if(excludeds==NULL || !std::binary_search(excludeds->begin(), excludeds->end(), *it)){
        if(v){
          v->push_back(*it);
        }
        remove(it);
      }else{
        it++;
      }
    }
    if(elements.size()!=count){
      setSortFlag(false);
//      destroyBoundRect();
    }
    return v;
  }


  bool AbstractElements::isModified(){
    for (VElements::iterator it = elements.begin(); it != elements.end(); it++) {
      if((*it)->isModified()){
        return true;
      }
    }
    return false;
  }

  /**
   * 原地重画与此组里所有元素相交的其它元素, 自己不重画，排除<code>excludeds</code>中的元素
   */
  void AbstractElements::redrawIntersection(const std::vector<AbstractElement*>* excludeds){
    if(!excludeds || excludeds->empty()){
      redrawAll(getAbstractElements());
    }else{
      std::vector<AbstractElement*> allExcludeds;
      allExcludeds.insert(allExcludeds.end(), elements.begin(), elements.end());
      allExcludeds.insert(allExcludeds.end(), excludeds->begin(), excludeds->end());
      redrawAll(&allExcludeds);
    }
  }


  /**
   * 增量移动到目标位置
   */
  void AbstractElements::moveBy(real dx, real dy){
    if(empty()){
      return;
    }
    //在目标区绘图
    for (vector<AbstractElement*>::iterator it = elements.begin(); it != elements.end(); it++) {
      AbstractElement* e = *it;
      e->moveBy(dx, dx);
    }

    createBoundRect();

    //销毁旧边界
//    destroyBoundRect();
  }

  /**
   * 返回元素索引位置, 如果元素不存在，返回-1
   */
  int AbstractElements::getIndex(AbstractElement* e){
    VElements::iterator it = getPosition(e);
    if(it != elements.end()){
      return it-elements.begin();
    }
    return -1;
  }


  /**
   * 返回元素索引位置, 如果元素不存在，返回elements.end()
   */
  std::vector<AbstractElement*>::iterator AbstractElements::getPosition (AbstractElement* e){
    if(isSorted()){
      VElementsIteratorPair p = std::equal_range(elements.begin(), elements.end(), e);
      if (p.first != p.second){
        return p.first;
      }else{
        return elements.end();
      }
    }else{
      return std::find(elements.begin(), elements.end(), e);
    }
  }


  /**
   * 检查是否包含此元素
   */
  bool AbstractElements::contains(const AbstractElement* e) const{
    if(isSorted()){
      return std::binary_search(elements.begin(), elements.end(), e);
    }else{
      return std::find(elements.begin(), elements.end(), e)!=elements.end();
    }
  }

  /**
   * 对元素进行排序
   */
  void AbstractElements::sort(){
    if(isSorted()){
      return;
    }
    std::sort(elements.begin(), elements.end());
    setSortFlag(true);
  }

//  /**
//   * 跟踪响应事件
//   */
//  bool AbstractElements::trackEvent(const Thk::Event* e){
//    if(!isEventEnabled()){
//      return false;
//    }
//
//    if(MouseEvent::isMouseEvent(e)){
//      //如果是鼠标事件
//      return handleMouseEvent((MouseEvent*)e);
//    }else{
//      return this->event(e);
//    }
//  }

//  /**
//   * 处理鼠标事件
//   */
//  bool AbstractElements::handleMouseEvent(const MouseEvent* me){
//    real x = me->x();
//    real y = me->y();
//    //向组中元素转发鼠标事件
//    AbstractElement* e = findByEventEnabled(x, y);
//    if(!e){
//      return false;
//    }
//    if(mouseHoveringElement && mouseHoveringElement != e){
//      mouseHoveringElement->mouseLeave(); //离开元素
//      //mouseLeaveElement(mouseHoveringElement);
//    }
//    if(mouseHoveringElement != e){
//      mouseHoveringElement = e;
//      mouseHoveringElement->mouseEnter();
//    }
//    return e->trackEvent(me);
//  }

  /**
   * 处理鼠标事件
   */
  bool AbstractElements::handleMouseEvent(const MouseEvent* me){
    real x = me->x();
    real y = me->y();
    //向组中元素转发鼠标事件
    AbstractElement* manualModeElement;
    AbstractElement* e;
    const std::vector<AbstractElement*>* els;
    //有可能没有层,那默认使用MEventMode_Hovering模式
    MouseEventMode mode = getLayer()?getLayer()->getMouseEventMode():MEventMode_Hovering;
    switch(mode){
      case MEventMode_Hovering:
        e = this->findByEventEnabled(x, y);
        if(mouseHoveringElement && mouseHoveringElement != e){
          mouseLeaveElement(mouseHoveringElement);
        }
        if(e){
          if(mouseHoveringElement != e){
            mouseHoveringElement = e;
            mouseHoveringElement->mouseEnter();
          }
          mouseHoveringElement->trackEvent(me);
        }
       break;
      case MEventMode_Top:
        els = getAbstractElements();
        if(!els->empty()){
          e = (*els)[els->size()-1];
          if(e->isEventEnabled() && e->isVisible() && e->intersects(x, y)){
            if(mouseHoveringElement != e){
              mouseHoveringElement = e;
              mouseHoveringElement->mouseEnter();
            }
            e->trackEvent(me);
          }else if(mouseHoveringElement){
            mouseLeaveElement(mouseHoveringElement);
          }
        }
       break;
      case MEventMode_Manual:
        manualModeElement = getLayer()->getManualModeElement();
        if(manualModeElement
            && manualModeElement->isEventEnabled()
            && manualModeElement->isVisible()
            && manualModeElement->intersects(x, y)){
          if(mouseHoveringElement != manualModeElement){
            mouseHoveringElement = manualModeElement;
            mouseHoveringElement->mouseEnter();
          }
          mouseHoveringElement->trackEvent(me);
        }else{
          if(mouseHoveringElement){
            mouseLeaveElement(mouseHoveringElement);
          }
        }
    }
    return false;
  }

  /**
   * 返回指定坐标 x,y上的最顶层可视并能响应事件的元素, 如果没有，返回NULL
   *
   * @param x X坐标
   * @param y Y坐标
   * @param excluded 被排除的元素
   *
   */
  AbstractElement* AbstractElements::findByEventEnabled(real x, real y, const AbstractElement* excluded) {
    const std::vector<AbstractElement*>* els = getAbstractElements();
    std::vector<AbstractElement*>::const_reverse_iterator it = els->rbegin();
    for (; it != els->rend(); it++) {
      AbstractElement* e = *it;
      if (e != excluded && e->isEventEnabled() && e->isVisible() && e->intersects(x, y)) {
        return e;
      }
    }
    return NULL;
  }


//  /**
//   * 发送鼠标离开事件
//   */
//  bool AbstractElements::mouseLeave(){
//    //如果鼠标最近一次悬停的元素存在，调用离开元素方法
//    if(mouseHoveringElement && mouseHoveringElement->mouseIsHovering() ){
//      //mouseHoveringElement->mouseLeave();
//      mouseLeaveElement(mouseHoveringElement);
//    }
//    return true;
//    //return AbstractElement::mouseLeave();
//  }


  void AbstractElements::remove(std::vector<AbstractElement*>::iterator it) {
    if (it != elements.end()) {
      //鼠标事件响应元素
      if(*it == mouseHoveringElement){
        mouseHoveringElement = NULL;
      }
      elements.erase(it);
    }
  }


  /**
   * 鼠标离开元素
   */
  void AbstractElements::mouseLeaveElement(AbstractElement* e){
    e->mouseLeave();
  }

  /**
   * 交换元素位置
   */
  void AbstractElements::swap(int lIdx, int rIdx){
    AbstractElement* e = elements[lIdx];
    elements[lIdx] = elements[rIdx];
    elements[rIdx] = e;
  }

}
